package main

import "fmt"

type TcpState string
type TcpEvent string
type TcpPkg string

// 数据包
const (
    pkgSync TcpPkg = "sync"
    pkgSyncAck TcpPkg = "ack"
    pkgAck TcpPkg = "ack"
)

// 事件
const (
	eventSync TcpEvent = "sync"
	eventSyncSend TcpEvent = "sync-send"
	eventSyncRecv TcpEvent = "sync-recv"
	eventSyncAckRecv TcpEvent = "sync-ack-recv"
	eventSyncAckSend TcpEvent = "sync"
	eventClose TcpEvent = "close"
	eventConnect TcpEvent = "connect"
    eventAckRecv TcpEvent = "ack-recv"
)

// 状态
const (
	stateSyncSent TcpState = "SYNC-SENT"
	stateSyncRecv TcpState = "SYNC-RECV"
	stateClosed TcpState = "CLOSED"
	stateEstab TcpState = "ESTAB"
	stateTimeWait TcpState = "TIME-WAIT"
	stateListen TcpState = "LISTEN"
)

type TcpConn struct {
    state TcpState
    ip string
    port int
}

type ActionState struct {
    action HandlerFunc
    state TcpState
}

type HandlerFunc func(Connectioner)

type Edges map[TcpEvent]ActionState

type FSM map[TcpState]Edges


func actionSendSync(conn Connectioner) {
    conn.SendPackage(pkgSync)
}

func actionRecvSyncAck(conn Connectioner) {
    conn.SendPackage(pkgAck)
}

func actionRecvSync(conn Connectioner) {
    conn.SendPackage(pkgSyncAck)
}

func actionNoop(conn Connectioner) {
}

var fsm FSM

func init() {
    // 定义状态迁移图
    fsm = map[TcpState]Edges {
        stateClosed: map[TcpEvent]ActionState {
            eventConnect: ActionState {
                state: stateSyncSent,
                action: actionSendSync,
            },
        },
        stateSyncSent: map[TcpEvent]ActionState {
            eventSyncAckRecv: ActionState {
                state: stateEstab,
                action: actionRecvSyncAck,
            },
        },
        stateListen: map[TcpEvent]ActionState {
            eventSyncRecv: ActionState {
                state: stateSyncRecv,
                action: actionRecvSync,
            },
        },
        stateSyncRecv: map[TcpEvent]ActionState {
            eventAckRecv: ActionState {
                state: stateEstab,
                action: actionNoop,
            },
        },
    }
}

type Connectioner interface {
    SendPackage(TcpPkg)
}

func NewTcpConn() *TcpConn {
    conn := TcpConn{}
    conn.state = stateClosed
    return &conn
}

func (c TcpConn) SendPackage(packet TcpPkg) {
}

func (c *TcpConn) RecvEvent(event TcpEvent) {
    edges, exists := fsm[c.state]
    if !exists {
        fmt.Println("Not support state")
        return
    }

    handler, exists := edges[event]
    if ! exists {
        fmt.Printf("Not support event: %v \n", event)
        return
    }

    handler.action(c)

    fmt.Printf("State from %v -> %v on event: %v\n", c.state, handler.state, event)
    c.state = handler.state
}

func (c TcpConn) Dump() {
    fmt.Printf("State: %v\n", c.state)
}



func main() {
    conn := NewTcpConn()
    conn.RecvEvent(eventConnect)
    conn.Dump()
    conn.RecvEvent(eventSyncAckRecv)
    conn.Dump()
}
